#define MT_MM     9
#define MT_NN     19
#define MT_WMASK  0xFFFFFFFFU
#define MT_UMASK  0xFFFFFFFEU
#define MT_LMASK  0x00000001U
#define MT_SHIFT0 12
#define MT_SHIFTB 7
#define MT_SHIFTC 15
#define MT_SHIFT1 18

#include "MyOCL.h"

typedef struct {
	unsigned int matrix_a;
	unsigned int mask_b;
	unsigned int mask_c;
	unsigned int seed;
} MersenneTwisterConfig;

class MersenneTwister : public MyOCL
{
private:
	cl_float				* randomValue;	// output values
	cl_uint					width;			// count values
	MersenneTwisterConfig	* mtConfigs;
	// the memory buffer that is used as input/output for OpenCL kernel 
	cl_mem					outputBuffer;
	cl_mem					mtConfigsBuffer;

	cl_program				program;
	// this program uses only one kernel and this serves as a handle to it 
	cl_kernel				kernel;

	// Initialize CL 
	void initializeCL(void);
	// Initialize Host application 
	void initializeHost(void);
	// run kernels cl 
	void runCLKernels(void);
	// releases OpenCL resources
	void cleanupCL(void);
	// releases program's resources 
	void cleanupHost(void);

public:
	MersenneTwister(cl_uint count);
	~MersenneTwister();

	cl_float * getArray() {return randomValue;}
};